﻿using DataMonitor_Tools.Tools.GPSConvert;
using DataMonitorMysql.MappingClass;
using Org.BouncyCastle.Bcpg;
using System;
using System.Data;
using System.IO;
using System.Text;

namespace DataMonitor_Tools.Tools
{
    public static class CSVFileWatch
    {
        public struct CSVFileWatchStruct
        {
            public byte status; //0正常，1有空值或nan，2文件空，3文件被占用,9为出错
            public string name;
            public List<string> headers;
            public List<List<double>> alldatalist;
        }
        /// <summary>
        /// 监控用的读取数据方法。筛选数据库中填写的csv文件里的字段名来读取数据到List<List<double>>，并降低了采样数
        /// </summary>
        /// <param name="filefullpath">文件路径</param>
        /// <param name="csvcollumnname">数据库里填写的字段名</param>
        /// <param name="monitortimes">降低采样频率</param>
        /// <returns></returns>
        public static async Task<CSVFileWatchStruct> CSVFileWatchCSVAsync(string filefullpath, string filename, int monitortimes)
        {
            var returnalllist = new CSVFileWatchStruct()
            {
                status=0,
                name = filename.Split('.')[0],
            };
            try
            {
                if (!FileOperator.FileIsUsed(filefullpath))
                {
                    if (!FileOperator.FileIsZero(filefullpath))
                    {
                        await Task.Run(() =>
                        {
                            Encoding encoding = Encoding.Default;
                            List<List<double>> datalist = new List<List<double>>();
                            using FileStream fs = new FileStream(filefullpath, System.IO.FileMode.Open, System.IO.FileAccess.Read, FileShare.ReadWrite);
                            StreamReader sr = new StreamReader(fs, encoding);
                            string strLine = "";
                            //记录每行记录中的各字段内容
                            string[]? aryLine = null;
                            string[]? tableHead = null;
                            int columnCount = 0;
                            //标示是否是读取的第一行
                            bool IsFirst = true;
                            int reset = monitortimes;
                            while ((strLine = sr.ReadLine()) != null)
                            {
                                if (IsFirst == true)
                                {
                                    //改为小写，去掉下划线，空格和N
                                    tableHead = strLine.Replace("_", "").Replace("N", "").Replace(" ", "").ToLower().Split(',');
                                    IsFirst = false;
                                    columnCount = tableHead.Length;
                                    returnalllist.headers= tableHead.ToList();
                                    for (int i = 0; i < columnCount; i++)
                                    {
                                        datalist.Add(new List<double>());
                                    }
                                }
                                else
                                {
                                    aryLine = strLine.Split(',');
                                    //判断是否需要读取数据，因为有降低采样数
                                    if (reset == monitortimes)
                                    {
                                        for (int i = 0; i < columnCount; i++)
                                        {
                                            var success = double.TryParse(aryLine[i], out double number);
                                            if ((!double.IsNaN(number)))
                                            {
                                                datalist[i].Add(number);
                                            }
                                            else
                                            {
                                                datalist[i].Add(-1.0);
                                                returnalllist.status = 1;
                                            }
                                        }
                                        reset = 1;
                                    }
                                    else
                                    {
                                        reset++;
                                    }

                                }
                            }
                            returnalllist.alldatalist = datalist;
                            sr.Close();
                            sr.Dispose();
                            fs.Close();
                            fs.Dispose();
                        });
                    }
                    else
                    {
                        returnalllist.status = 2;
                    }
                }
                else
                {
                    returnalllist.status = 3;
                }
                return returnalllist;
            }
            catch (Exception ex)
            {
                ErrorMessage.GetErrorMessage(filename, ex.Message);
                returnalllist.status = 9;
                return returnalllist;
            }
        }
        /// <summary>
        /// 监控用的读取数据方法2。添加了文件被占用会等待占用完继续读取的功能，筛选数据库中填写的csv文件里的字段名来读取数据到List<List<double>>，并降低了采样数
        /// </summary>
        /// <param name="filefullpath"></param>
        /// <param name="filename"></param>
        /// <param name="monitortimes"></param>
        /// <returns></returns>
        public static async Task<CSVFileWatchStruct> CSVFileWatchCSVAsyncV2(string filefullpath, string filename, int monitortimes)
        {
            var returnalllist = new CSVFileWatchStruct()
            {
                status = 0,
                name = filename.Split('.')[0],
            };
            while (true)
            {
                try
                {
                    using (FileStream fs = new FileStream(filefullpath, System.IO.FileMode.Open, System.IO.FileAccess.Read, FileShare.ReadWrite))
                    {
                        if (fs != null)
                        break;
                    }
                    Thread.Sleep(100);
                }
                catch(Exception ex)
                {
                    ErrorMessage.GetErrorMessage(filename, ex.Message);
                }
            }
            try
            {
                if (!FileOperator.FileIsZero(filefullpath))
                {
                    await Task.Run(() =>
                    {
                        Encoding encoding = Encoding.Default;
                        List<List<double>> datalist = new List<List<double>>();
                        using FileStream fs = new FileStream(filefullpath, System.IO.FileMode.Open, System.IO.FileAccess.Read, FileShare.ReadWrite);
                        StreamReader sr = new StreamReader(fs, encoding);
                        string strLine = "";
                        //记录每行记录中的各字段内容
                        string[]? aryLine = null;
                        string[]? tableHead = null;
                        int columnCount = 0;
                        //标示是否是读取的第一行
                        bool IsFirst = true;
                        int reset = monitortimes;
                        while ((strLine = sr.ReadLine()) != null)
                        {
                            if (IsFirst == true)
                            {
                                //改为小写，去掉下划线，空格和N
                                tableHead = strLine.Replace("_", "").Replace("N", "").Replace(" ", "").ToLower().Split(',');
                                IsFirst = false;
                                columnCount = tableHead.Length;
                                returnalllist.headers = tableHead.ToList();
                                for (int i = 0; i < columnCount; i++)
                                {
                                    datalist.Add(new List<double>());
                                }
                            }
                            else
                            {
                                aryLine = strLine.Split(',');
                                //判断是否需要读取数据，因为有降低采样数
                                if (reset == monitortimes)
                                {
                                    for (int i = 0; i < columnCount; i++)
                                    {
                                        var success = double.TryParse(aryLine[i], out double number);
                                        if ((!double.IsNaN(number)))
                                        {
                                            datalist[i].Add(number);
                                        }
                                        else
                                        {
                                            datalist[i].Add(-1.0);
                                            returnalllist.status = 0;
                                        }
                                    }
                                    reset = 1;
                                }
                                else
                                {
                                    reset++;
                                }

                            }
                        }
                        returnalllist.alldatalist = datalist;
                        sr.Close();
                        sr.Dispose();
                        fs.Close();
                        fs.Dispose();
                    });
                }
                else
                {
                    returnalllist.status = 2;
                }
                return returnalllist;
            }
            catch (Exception ex)
            {
                ErrorMessage.GetErrorMessage(filename, ex.Message+" 状态码："+ returnalllist.status);
                returnalllist.status = 9;
                return returnalllist;
            }

        }

        /// <summary>
        /// 计算一个csv文件的里程并返回
        /// </summary>
        /// <param name="spd"></param>
        /// <param name="lastingtime"></param>
        /// <returns></returns>
        public static async Task<double> CalSpdAverageAsync(this List<double> spd)
        {
            double sdpavg = 0;
            await Task.Run(() =>
            {
                sdpavg = spd.Sum() > 0 ? (spd.Sum()) / (spd.Count) : 0;
                //sdistance = Math.Round(speedaverage / 3600 * lastingtime, 2);
            });
            return sdpavg;
        }
        /// <summary>
        /// 帅选出lat，lon并再降低采样率到10个点和其他图表里的数据
        /// </summary>
        /// <param name="cSVFileWatchStruct"></param>
        /// <param name="dm_Props_User"></param>
        /// <returns></returns>
        public static async Task<List<List<double>>> CSVFileWatchStructEditAsync(CSVFileWatchStruct cSVFileWatchStruct, dm_props_user dm_Props_User)
        {
            List<List<double>> results = new List<List<double>>();
            await Task.Run(() => {
                //if (cSVFileWatchStruct.alldatalist.Count > 0)
                //{
                //    //添加time列
                //    results.Add(cSVFileWatchStruct.alldatalist[0]);
                //}
                var t1 = dm_Props_User.echart1chan.Replace("_", "").Replace("N", "").Replace(" ", "").ToLower().Split(",");
                var t2 = dm_Props_User.echart2chan.Replace("_", "").Replace("N", "").Replace(" ", "").ToLower().Split(",");
                var t3 = dm_Props_User.echart3chan.Replace("_", "").Replace("N", "").Replace(" ", "").ToLower().Split(",");
                var t4 = dm_Props_User.echart4chan.Replace("_", "").Replace("N", "").Replace(" ", "").ToLower().Split(",");
                var t5 = dm_Props_User.echart5chan.Replace("_", "").Replace("N", "").Replace(" ", "").ToLower().Split(",");
                var t6 = dm_Props_User.echart6chan.Replace("_", "").Replace("N", "").Replace(" ", "").ToLower().Split(",");
                var tall = t1.Concat(t2).Concat(t3).Concat(t4).Concat(t5).Concat(t6).ToArray();

                var latindex = cSVFileWatchStruct.headers.IndexOf("lat");
                var lonindex = cSVFileWatchStruct.headers.IndexOf("lon");
                int inter = cSVFileWatchStruct.alldatalist[0].Count / 5;
                List<double> lat = new List<double>();
                List<double> lon = new List<double>();
                if (latindex != -1 && lonindex != -1)
                {
                    var lat1 = cSVFileWatchStruct.alldatalist[latindex].FirstOrDefault();
                    var lon1 = cSVFileWatchStruct.alldatalist[lonindex].FirstOrDefault();
                    var newgps1 = GpsCoordinate.GpsToNewGps(lat1, lon1, 6);
                    lat.Add(newgps1._wgLat);
                    lon.Add(newgps1._wgLon);

                    //lat.Add(cSVFileWatchStruct.alldatalist[latindex].FirstOrDefault());
                    //lon.Add(cSVFileWatchStruct.alldatalist[lonindex].FirstOrDefault());
                    //for (int i = 0; i < 5; i++)
                    //{
                    //    lat.Add(cSVFileWatchStruct.alldatalist[latindex].Skip(i * inter).Take(1).FirstOrDefault());
                    //    //lat.Add(cSVFileWatchStruct.alldatalist[latindex].LastOrDefault());
                    //    lon.Add(cSVFileWatchStruct.alldatalist[lonindex].Skip(i * inter).Take(1).FirstOrDefault());
                    //    //lon.Add(cSVFileWatchStruct.alldatalist[lonindex].LastOrDefault());
                    //}

                    var lat2 = cSVFileWatchStruct.alldatalist[latindex].LastOrDefault();
                    var lon2 = cSVFileWatchStruct.alldatalist[lonindex].LastOrDefault();
                    var newgps2 = GpsCoordinate.GpsToNewGps(lat2, lon2, 6);
                    lat.Add(newgps2._wgLat);
                    lon.Add(newgps2._wgLon);

                    //lat.Add(cSVFileWatchStruct.alldatalist[latindex].LastOrDefault());
                    //lon.Add(cSVFileWatchStruct.alldatalist[lonindex].LastOrDefault());
                    results.Add(lat);
                    results.Add(lon);
                }
                foreach (var t in tall)
                {
                    var idx = cSVFileWatchStruct.headers.IndexOf(t);
                    if (idx != -1)
                    {
                        results.Add(cSVFileWatchStruct.alldatalist[idx]);
                    }
                }


            });
            return results;
        }

        /// <summary>
        /// 读取某个csv文件中的spd列数据并保存为List<double>返回
        /// </summary>
        /// <param name="filefullpath"></param>
        /// <param name="monitortimes"></param>
        /// <returns></returns>
        public static async Task<List<double>> CSVFileSelectChanAsync(this string filefullpath,string channame, int monitortimes)
        {
            List<double> results = new List<double>();   
            while (true)
            {
                try
                {
                    using (FileStream fs = new FileStream(filefullpath, System.IO.FileMode.Open, System.IO.FileAccess.Read, FileShare.ReadWrite))
                    {
                        if (fs != null)
                            break;
                    }
                    Thread.Sleep(100);
                }
                catch (Exception ex)
                {
                    ErrorMessage.GetErrorMessage(filefullpath, ex.Message);
                }
            }
            try
            {
                if (!FileOperator.FileIsZero(filefullpath))
                {
                    await Task.Run(() =>
                    {
                        Encoding encoding = Encoding.Default;
                        using FileStream fs = new FileStream(filefullpath, System.IO.FileMode.Open, System.IO.FileAccess.Read, FileShare.ReadWrite);
                        StreamReader sr = new StreamReader(fs, encoding);
                        string strLine = "";
                        //记录每行记录中的各字段内容
                        string[]? aryLine = null;
                        string[]? tableHead = null;
                        int columnCount = 0;
                        //标示是否是读取的第一行
                        bool IsFirst = true;
                        int reset = monitortimes;
                        int spdidx = -1;
                        while ((strLine = sr.ReadLine()) != null)
                        {
                            if (IsFirst == true)
                            {
                                //改为小写，去掉下划线，空格和N
                                tableHead = strLine.Replace("_", "").Replace("N", "").Replace(" ", "").ToLower().Split(',');
                                spdidx =tableHead.ToList().IndexOf(channame);
                                IsFirst = false;
                                columnCount = tableHead.Length;
                            }
                            else
                            {
                                aryLine = strLine.Split(',');
                                //判断是否需要读取数据，因为有降低采样数
                                if (reset == monitortimes)
                                {
                                    if (spdidx >0 && spdidx < tableHead?.Length)
                                    {
                                        var success = double.TryParse(aryLine[spdidx], out double number);
                                        if ((!double.IsNaN(number)))
                                        {
                                            results.Add(number);
                                        }
                                        else
                                        {
                                            results.Add(0);
                                        }
                                    }
                                    else
                                    {
                                        ErrorMessage.GetErrorMessage(filefullpath, "没有找到spd列");
                                    }
                                    reset = 1;
                                }
                                else
                                {
                                    reset++;
                                }
                            }
                        }
                        sr.Close();
                        sr.Dispose();
                        fs.Close();
                        fs.Dispose();
                    });
                }
               
            }
            catch (Exception ex)
            {
                ErrorMessage.GetErrorMessage(filefullpath, ex.Message);
            }
            return results;
        }


        /// <summary>
        /// 读取某个csv文件中的lat和lon列第一行数据并保存为List<double>返回，这里的降低采样率其实没什么用，只读第一行数据
        /// </summary>
        /// <param name="filefullpath"></param>
        /// <param name="monitortimes"></param>
        /// <returns></returns>
        public static async Task<List<double>> CSVFileSelectGpsAsync(this string filefullpath, int monitortimes)
        {
            List<double> results = new List<double>();
            while (true)
            {
                try
                {
                    using (FileStream fs = new FileStream(filefullpath, System.IO.FileMode.Open, System.IO.FileAccess.Read, FileShare.ReadWrite))
                    {
                        if (fs != null)
                            break;
                    }
                    Thread.Sleep(100);
                }
                catch (Exception ex)
                {
                    ErrorMessage.GetErrorMessage(filefullpath, ex.Message);
                }
            }
            try
            {
                if (!FileOperator.FileIsZero(filefullpath))
                {
                    await Task.Run(() =>
                    {
                        Encoding encoding = Encoding.Default;
                        using FileStream fs = new FileStream(filefullpath, System.IO.FileMode.Open, System.IO.FileAccess.Read, FileShare.ReadWrite);
                        StreamReader sr = new StreamReader(fs, encoding);
                        string strLine = "";
                        //记录每行记录中的各字段内容
                        string[]? aryLine = null;
                        string[]? tableHead = null;
                        int columnCount = 0;
                        //标示是否是读取的第一行
                        bool IsFirst = true;
                        int reset = monitortimes;
                        int latidx=-1,lonidx = -1;
                        while ((strLine = sr.ReadLine()) != null)
                        {
                            if (IsFirst == true)
                            {
                                //改为小写，去掉下划线，空格和N
                                tableHead = strLine.ToLower().Split(',');
                                latidx = tableHead.ToList().IndexOf("lat");
                                lonidx = tableHead.ToList().IndexOf("lon");
                                IsFirst = false;
                                columnCount = tableHead.Length;
                            }
                            else
                            {
                                aryLine = strLine.Split(',');
                                //判断是否需要读取数据，因为有降低采样数
                                if (reset == monitortimes)
                                {
                                    if (latidx > 0 && lonidx > 0)
                                    {
                                        var latsuccess = double.TryParse(aryLine[latidx], out double lat);
                                        var lonsuccess = double.TryParse(aryLine[lonidx], out double lon);
                                        var latisint=int.TryParse(lat.ToString(), out int num1);
                                        var lonisint = int.TryParse(lon.ToString(), out int num2);
                                        if ((!double.IsNaN(lat))&& (!double.IsNaN(lon)))
                                        {
                                            //确定不是整数才添加经纬度
                                            if (!latisint && !lonisint)
                                            {
                                                results.Add(lat);
                                                results.Add(lon);
                                                break;
                                            }
                                        }
                                        
                                    }
                                    else
                                    {
                                        ErrorMessage.GetErrorMessage(filefullpath, "没有找到经纬度数据列");
                                    }
                                    reset = 1;
                                }
                                else
                                {
                                    reset++;
                                }
                            }
                        }
                        sr.Close();
                        sr.Dispose();
                        fs.Close();
                        fs.Dispose();
                    });
                }

            }
            catch (Exception ex)
            {
                ErrorMessage.GetErrorMessage(filefullpath, ex.Message);
            }
            return results;
        }

    }
}
